//
//  ByBlueToothHandleModel.m
//  laserdevice_ios
//
//  Created by pro on 16/12/8.
//  Copyright © 2016年 com.itboye. All rights reserved.
//

#import "ByBlueToothHandleModel.h"

//#define channelOnPeropheralView @"peripheralView"
#define channelOnCharacteristicView @"CharacteristicView"

// test
#import "ByBlueToothMeaturesL1Model.h"


@implementation ByBlueToothHandleModel

static ByBlueToothHandleModel *instance;


+ (ByBlueToothHandleModel *)shareInstance {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[ByBlueToothHandleModel alloc] init];

    });
    return instance;
}
+ (id)allocWithZone:(struct _NSZone *)zone {
    
    if (instance == nil) {
        instance = [super allocWithZone:zone];
    }
    return instance;
}


//babyDelegate
-(void)babyDelegateTest{
    
    __weak typeof(self)weakSelf = self;
    BabyRhythm *rhythm = [[BabyRhythm alloc]init];
    
    
    //设置设备连接成功的委托,同一个baby对象，使用不同的channel切换委托回调
    [_baby setBlockOnConnectedAtChannel:channelOnPeropheralView block:^(CBCentralManager *central, CBPeripheral *peripheral) {
//        [ByCoreToolAlert showOnlyText:[NSString stringWithFormat:@"设备：%@--连接成功",peripheral.name]];

        [ByCoreToolAlert hideHud];
//        weakSelf.characteristic = nil;
        
        [UIAlertView showWithTitle:nil message:[NSString stringWithFormat:@"%@:%@",peripheral.name, STRING(@"lianjiechenggong")] cancelButtonTitle:nil otherButtonTitles:@[STRING(@"queding")] tapBlock:^(UIAlertView *alertView, NSInteger buttonIndex) {
            [ByBlueToothHandleModel shareInstance].needShowAlert = YES;

            if (weakSelf.successBlock) {
                weakSelf.successBlock();
            }
        }];
    }];
    
    //设置设备连接失败的委托
    [_baby setBlockOnFailToConnectAtChannel:channelOnPeropheralView block:^(CBCentralManager *central, CBPeripheral *peripheral, NSError *error) {
        NSLog(@"设备：%@--连接失败",peripheral.name);
//        [ByCoreToolAlert showOnlyText:[NSString stringWithFormat:@"设备：%@--连接失败",peripheral.name]];

    }];
    
    //设置设备断开连接的委托
    [_baby setBlockOnDisconnectAtChannel:channelOnPeropheralView block:^(CBCentralManager *central, CBPeripheral *peripheral, NSError *error) {
        NSLog(@"设备：%@--断开连接",peripheral.name);
//        [ByCoreToolAlert showOnlyText:[NSString stringWithFormat:@"设备：%@--断开失败",peripheral.name]];

        if ([ByBlueToothHandleModel shareInstance].needShowAlert == NO) {
            weakSelf.characteristic = nil;
            return ;
        }
        [UIAlertView showWithTitle:nil message:STRING(@"shebeiduankai") cancelButtonTitle:nil otherButtonTitles:@[STRING(@"queding")] tapBlock:^(UIAlertView *alertView, NSInteger buttonIndex) {
            
            [ByBlueToothHandleModel shareInstance].needShowAlert = YES;
        }];
        weakSelf.characteristic = nil;

    }];
    

    
    //设置发现设备的Services的委托
    [_baby setBlockOnDiscoverServicesAtChannel:channelOnPeropheralView block:^(CBPeripheral *peripheral, NSError *error) {
//        [ByCoreToolAlert showOnlyText:@"发现设备的Services的委托"];

        if (weakSelf.characteristic.isNotifying) {
            return;
        }
        
        for (CBService *service in peripheral.services) {
            
            for (int row = 0; row < service.characteristics.count; row++) {
                CBCharacteristic *c = service.characteristics[row];
                
                if (c.properties & CBCharacteristicPropertyNotify || c.properties & CBCharacteristicPropertyIndicate) {
                    
                    weakSelf.characteristic = c;
                    [weakSelf startNotify];
                    
                }
            }
        }
        
        [rhythm beats];
    }];
    //设置发现设service的Characteristics的委托
    [_baby setBlockOnDiscoverCharacteristicsAtChannel:channelOnPeropheralView block:^(CBPeripheral *peripheral, CBService *service, NSError *error) {
        NSLog(@"===service name:%@",service.UUID);
//        [ByCoreToolAlert showOnlyText:@"发现设service的Characteristics的委托"];
        
        if (weakSelf.characteristic.isNotifying) {
            return;
        }

        for (CBService *service in peripheral.services) {
            
            for (int row = 0; row < service.characteristics.count; row++) {
                CBCharacteristic *c = service.characteristics[row];
                
                if (c.properties & CBCharacteristicPropertyNotify || c.properties & CBCharacteristicPropertyIndicate) {
                    
                    weakSelf.characteristic = c;
                    [weakSelf startNotify];
                    
                }
            }
        }
        
        
    }];
    //设置读取characteristics的委托
    [_baby setBlockOnReadValueForCharacteristicAtChannel:channelOnPeropheralView block:^(CBPeripheral *peripheral, CBCharacteristic *characteristics, NSError *error) {
        NSLog(@"characteristic name:%@ value is:%@",characteristics.UUID,characteristics.value);
    }];
    //设置发现characteristics的descriptors的委托
    [_baby setBlockOnDiscoverDescriptorsForCharacteristicAtChannel:channelOnPeropheralView block:^(CBPeripheral *peripheral, CBCharacteristic *characteristic, NSError *error) {
        NSLog(@"===characteristic name:%@",characteristic.service.UUID);
        for (CBDescriptor *d in characteristic.descriptors) {
            NSLog(@"CBDescriptor name is :%@",d.UUID);
        }
    }];
    //设置读取Descriptor的委托
    [_baby setBlockOnReadValueForDescriptorsAtChannel:channelOnPeropheralView block:^(CBPeripheral *peripheral, CBDescriptor *descriptor, NSError *error) {
        NSLog(@"Descriptor name:%@ value is:%@",descriptor.characteristic.UUID, descriptor.value);
    }];
    
    //读取rssi的委托
    [_baby setBlockOnDidReadRSSI:^(NSNumber *RSSI, NSError *error) {
        NSLog(@"setBlockOnDidReadRSSI:RSSI:%@",RSSI);
    }];
    
    
    //设置beats break委托
    [rhythm setBlockOnBeatsBreak:^(BabyRhythm *bry) {
        NSLog(@"setBlockOnBeatsBreak call");
        
        //如果完成任务，即可停止beat,返回bry可以省去使用weak rhythm的麻烦
        //        if (<#condition#>) {
        //            [bry beatsOver];
        //        }
        
    }];
    
    //设置beats over委托
    [rhythm setBlockOnBeatsOver:^(BabyRhythm *bry) {
        NSLog(@"setBlockOnBeatsOver call");
    }];
    
    //扫描选项->CBCentralManagerScanOptionAllowDuplicatesKey:忽略同一个Peripheral端的多个发现事件被聚合成一个发现事件
    NSDictionary *scanForPeripheralsWithOptions = @{CBCentralManagerScanOptionAllowDuplicatesKey:@YES};
    /*连接选项->
     CBConnectPeripheralOptionNotifyOnConnectionKey :当应用挂起时，如果有一个连接成功时，如果我们想要系统为指定的peripheral显示一个提示时，就使用这个key值。
     CBConnectPeripheralOptionNotifyOnDisconnectionKey :当应用挂起时，如果连接断开时，如果我们想要系统为指定的peripheral显示一个断开连接的提示时，就使用这个key值。
     CBConnectPeripheralOptionNotifyOnNotificationKey:
     当应用挂起时，使用该key值表示只要接收到给定peripheral端的通知就显示一个提
     */
    NSDictionary *connectOptions = @{CBConnectPeripheralOptionNotifyOnConnectionKey:@YES,
                                     CBConnectPeripheralOptionNotifyOnDisconnectionKey:@YES,
                                     CBConnectPeripheralOptionNotifyOnNotificationKey:@YES};
    
    [_baby setBabyOptionsAtChannel:channelOnPeropheralView scanForPeripheralsWithOptions:scanForPeripheralsWithOptions connectPeripheralWithOptions:connectOptions scanForPeripheralsWithServices:nil discoverWithServices:nil discoverWithCharacteristics:nil];
    
}



- (void)connectPeripheral {
    [ByCoreToolAlert showLoadind:@"正在连接设备"];
    self.baby.having(self.currPeripheral).and.channel(channelOnPeropheralView).then.connectToPeripherals().discoverServices().discoverCharacteristics().readValueForCharacteristic().discoverDescriptorsForCharacteristic().readValueForDescriptors().begin();
    

}

// 开始通知
- (void)startNotify {
    
    __weak typeof(self) weakSelf = self;
    
    [self.baby setBlockOnReadValueForCharacteristicAtChannel:channelOnPeropheralView block:^(CBPeripheral *peripheral, CBCharacteristic *characteristics, NSError *error) {
        
        NSLog(@"数据：%@", [weakSelf dataToHexString:characteristics.value]);
        
    }];
    //设置发现characteristics的descriptors的委托
    [self.baby setBlockOnDiscoverDescriptorsForCharacteristicAtChannel:channelOnPeropheralView block:^(CBPeripheral *peripheral, CBCharacteristic *characteristic, NSError *error) {
        for (CBDescriptor *d in characteristic.descriptors) {
            NSLog(@"发现特征值:%@", d);
        }
    }];
    
    //设置写数据成功的block
    [self.baby setBlockOnDidWriteValueForCharacteristicAtChannel:channelOnPeropheralView block:^(CBCharacteristic *characteristic, NSError *error) {
        NSLog(@"setBlockOnDidWriteValueForCharacteristicAtChannel characteristic:%@ and new value:%@",characteristic.UUID, characteristic.value);
    }];
    
    //设置通知状态改变的block
    [self.baby setBlockOnDidUpdateNotificationStateForCharacteristicAtChannel:channelOnPeropheralView block:^(CBCharacteristic *characteristic, NSError *error) {
        NSLog(@"uid:%@,isNotifying:%@",characteristic.UUID,characteristic.isNotifying?@"on":@"off");
    }];

    
    if(!self.characteristic.isNotifying) {
        
        [self.currPeripheral setNotifyValue:YES forCharacteristic:self.characteristic];
        [self.baby notify:self.currPeripheral
           characteristic:self.characteristic
                    block:^(CBPeripheral *peripheral, CBCharacteristic *characteristics, NSError *error) {
                        
                        NSLog(@"数据:%@", characteristics.value);
                        
                        if (_callBack) {
                            _callBack([self dataToHexString:characteristics.value]);
                        }
                    }];
    }
}

- (void)startDistanceMeasure:(void (^)(NSString *dataHex))callBack withOneMeasure:(BOOL)needOneMeasure {
    
    _callBack = callBack;
    
    if (self.characteristic && needOneMeasure) {
        NSString *d = @"F54D4B5343303134393038303030523130FA";
        NSData *data = [self hexStringToData:d];
        [self.currPeripheral writeValue:data forCharacteristic:self.characteristic type:CBCharacteristicWriteWithoutResponse];
    }
    
}



// 开始实时测量
- (void)startRealTimeMeasure:(void (^)(NSString *dataHex))callBack {
    
    // 设置回调
    _callBack = callBack;
    
    NSString *d = @"F54D4B53433031343930383030304C3330FA";
    NSData *data = [self hexStringToData:d];
    [self.currPeripheral writeValue:data forCharacteristic:self.characteristic type:CBCharacteristicWriteWithoutResponse];
}
// 关闭实时测量
- (void)closeRealTimeMeasure {
    
    _callBack = nil;
    
    
    NSString *d = @"F54D4B5343303134393038303030535430FA";
    NSData *data = [self hexStringToData:d];
    [self.currPeripheral writeValue:data forCharacteristic:self.characteristic type:CBCharacteristicWriteWithoutResponse];
    
    
}
// 获取历史数据
- (void)getHistoryMeasure:(void (^)(NSString *dataHex))callBack {

    _callBack = callBack;
    
    NSString *d = @"F54D4B53433031343930383039394C3130FA";
    NSData *data = [self hexStringToData:d];
    [self.currPeripheral writeValue:data forCharacteristic:self.characteristic type:CBCharacteristicWriteWithoutResponse];

}

// 关闭历史数据测量
- (void)closeHistoryMeasure {
    
    _callBack = nil;
    
}

#pragma mark - 辅助
//NSdata转为十六进制字符串
- (NSString *)dataToHexString:(NSData *)data
{
    NSUInteger          len = [data length];
    char *              chars = (char *)[data bytes];
    NSMutableString *   hexString = [[NSMutableString alloc] init];
    
    for(NSUInteger i = 0; i < len; i++ ){
        [hexString appendString:[NSString stringWithFormat:@"%0.2hhx", chars[i]]]; //[NSString stringWithFormat:@"%02x", chars[i]若不与上0xff会出现错误值
    }
    return [hexString stringByReplacingOccurrencesOfString:@" " withString:@""]; //iOS9会加入空格
}
//十六进制NSString转为NSdata
- (NSData *)hexStringToData:(NSString *)string
{
    int len = (int)[string length] / 2;    // Target length
    unsigned char *buf = malloc(len);
    unsigned char *whole_byte = buf;
    char byte_chars[3] = {'\0','\0','\0'};
    
    int i;
    for (i=0; i < [string length] / 2; i++) {
        byte_chars[0] = [string characterAtIndex:i*2];
        byte_chars[1] = [string characterAtIndex:i*2+1];
        *whole_byte = strtol(byte_chars, NULL, 16);
        whole_byte++;
    }
    
    NSData *data = [NSData dataWithBytes:buf length:len];
    free( buf );
    return data;
}
@end
